#ifndef __FACEBOOK_NEW_H__
#define __FACEBOOK_NEW_H__

//=====================
//Facebook client class
//by Alexander Samarin
//
//v 1.0
//=====================

#include "curl.h"

#include <string>
#include <sstream>
#include <list>
#include <vector>



#include <cassert>

#define FACEBOOK_APIVER "1.0"
#define FACEBOOK_SECURELOGINURL "https://login.facebook.com/login.php"
#define FACEBOOK_DESKTOPAPP_NEWAPPROVEMENTURL "http://www.new.facebook.com/tos.php?v=1.0"
#define FACEBOOK_DESKTOPAPP_APPROVEMENTURL "http://www.facebook.com/tos.php?v=1.0"
#define FACEBOOK_ADDAPPURL "http://www.facebook.com/add.php"
#define FACEBOOK_LOGOUTURL "http://www.facebook.com/logout.php"
#define FACEBOOK_DESKTOPAPP_FINALURL "http://www.facebook.com/desktopapp.php"

//this script for getting photo image size is located on our server
#define FACEBOOK_IMAGESIZESCRIPTURL "http://www.boomzap.com/fbutil_imagesize.php"

#define FACEBOOK_PROFILEINFOQUERY "name,first_name,birthday,sex,is_app_user,status,timezone,hometown_location,pic,pic_big,pic_small,pic_square"

#define FACEBOOK_USERAGENT "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.2a) Gecko/20021021"


//facebook callback func typedef
typedef void(*FacebookCallbackFunc)(void);


struct XMLNode;

struct FacebookPhotoSize
{
	FacebookPhotoSize(){Width = 0; Height = 0;};
	int Width;
	int Height;
};

//Facebook profile information bits we use

enum FACEBOOK_PROFILEINFO
{
	FBPROFILEINFO_NAME,
	FBPROFILEINFO_FIRSTNAME,
	FBPROFILEINFO_BIRTHDAY,
	FBPROFILEINFO_SEX,
	FBPROFILEINFO_ISAPPUSER,
	FBPROFILEINFO_STATUS,
	FBPROFILEINFO_TIMEZONE,
	FBPROFILEINFO_CITY,
	FBPROFILEINFO_COUNTRY,
	FBPROFILEINFO_PHOTOURL
};

enum FACEBOOK_FEEDITEM
{
	FBFEEDITEM_STORY,
	FBFEEDITEM_ACTION
};

struct FacebookFeedItem
{

	FacebookFeedItem()
	{
		m_TitleFBML = "";
		m_BodyFBML = "";

		m_Image1URL = "";
		m_Image1DestinationURL = "";
		m_Image2URL = "";
		m_Image2DestinationURL = "";
		m_Image3URL = "";
		m_Image3DestinationURL = "";
		m_Image4URL = "";
		m_Image4DestinationURL = "";
	};

	std::string			m_TitleFBML;
	std::string			m_BodyFBML;

	std::string			m_Image1URL;
	std::string			m_Image1DestinationURL;

	std::string			m_Image2URL;
	std::string			m_Image2DestinationURL;

	std::string			m_Image3URL;
	std::string			m_Image3DestinationURL;

	std::string			m_Image4URL;
	std::string			m_Image4DestinationURL;

};

struct FacebookProfileInfo
{
	FacebookProfileInfo()
	{
		Name = "";
		FirstName = "";
		Birthday = "";
		Sex = "";
		IsAppUser = "";
		Status = "";
		Timezone = "";
		City = "";
		Country = "";
		PhotoURL = "";
	}

	std::string		  Name;
	std::string       FirstName;
	std::string		  Birthday;
	std::string		  Sex;
	std::string		  IsAppUser;
	std::string		  Status;
	std::string		  Timezone;
	std::string		  City;
	std::string		  Country;
	std::string		  PhotoURL;
	FacebookPhotoSize PhotoSize;

};//struct FacebookProfileInfo

//Facebook user data structure
struct FacebookUser
{
	//constructor
	FacebookUser(const std::string& UserEmail, const std::string& UserPassword) : m_UserProfileInfo(), m_FriendsIDs(), m_FriendsProfileInfo(), m_FriendsPhotos()
	{
		//curl easy init
		m_pCurl = curl_easy_init();
		assert(m_pCurl != NULL);

		m_UserEmail = UserEmail;
		m_UserPassword = UserPassword;

		m_LoginToken = "";
		m_LoginSession = "";
		m_SessionSecret = "";

		m_LoggedIn = false;

		m_UserID = "";
		m_UserPhoto = "";
	};

	//destructor
	~FacebookUser()
	{
		//curl easy cleanup
		curl_easy_cleanup(m_pCurl);
	};

	//curl handle
	CURL* m_pCurl;

	//user email and password
	std::string						 m_UserEmail;
	std::string						 m_UserPassword;

	//login related strings
	std::string						 m_LoginToken;
	std::string						 m_LoginSession;
	std::string						 m_SessionSecret;
	
	//login status
	bool							 m_LoggedIn;

	//user ID
	std::string						 m_UserID;

	//profile info
	FacebookProfileInfo				 m_UserProfileInfo;

	//friends info
	std::vector<std::string>		 m_FriendsIDs;
	std::vector<FacebookProfileInfo> m_FriendsProfileInfo;

	//app and non-app friends
	std::vector<int>				 m_AppFriendsIndexes;
	std::vector<int>				 m_NonAppFriendsIndexes;

	//photos
	std::string						 m_UserPhoto;
	std::vector<std::string>		 m_FriendsPhotos;

};//struct FacebookUser



//Main Facebook class
class Facebook
{
public:

	//Constructor and destructor
	Facebook();
	~Facebook();

	//Instance
	static Facebook&				Instance()
	{
		static Facebook		Inst;
		return Inst;
	}

	static int ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);


	//curl write callback function
	static size_t Write_Callback(void *ptr, size_t size, size_t nmemb, void *userp);

	//Init method
	bool Init(const std::string& AppKey, const std::string& AppSecret, const std::string& ApiServer = "api.facebook.com/restserver.php", const std::string& LoginURL = "http://api.facebook.com/login.php");

	//Setting Callback func
	void SetCallbackFunc(FacebookCallbackFunc pFunc) {m_pCallbackFunc = pFunc;};

	//Get Error description method
	const std::string& GetErrorDescription() {return m_ErrorDescription;};

	//If facebook site changed
	bool IsFacebookSiteChanged() {return m_FacebookSiteChanged;};

	//If login/password was wrong during last login call
	bool IsInvalidLoginPassword() {return m_InvalidLoginPassword;};

	//working with users
	bool SetCurrentUser(const std::string& UserEmail, const std::string& UserPassword);
	bool RemoveCurrentUser(); //useful when user can't login because of invalid email or password.

	//adding facebook app method
	bool AddApplicationToProfile(const std::string& AppToAddKey, bool AllowProfile = true, bool AllowNavLink = true, bool AllowFeeds = true, bool AllowProfileActions = true);

	//working with current user
	bool CurUser_Login();

	//data fetching routines
	bool CurUser_FetchUserInfo();
	bool CurUser_FetchFriendsInfo();

	//get data routines
	bool CurUser_GetUserID(std::string& Result);
	bool CurUser_GetUserInfo(FACEBOOK_PROFILEINFO InfoField, std::string& Result);

	int	CurUser_GetFriendsCount();

	bool CurUser_GetFriendID(int FriendIndex, std::string& Result);
	bool CurUser_GetFriendInfo(int FriendIndex, FACEBOOK_PROFILEINFO InfoField, std::string& Result);

	//photo fetching routines
	bool CurUser_FetchUserPhoto();
	bool CurUser_FetchFriendPhoto(int FriendIndex);

	//getting photo data routines
	int CurUser_UserPhoto_GetSize();
	const std::string* CurUser_UserPhoto_GetData();

	int CurUser_FriendPhoto_GetSize(int FriendIndex);
	const std::string* CurUser_FriendPhoto_GetData(int FriendIndex);

	//getting photo size routines
	int CurUser_UserPhoto_GetWidth();
	int CurUser_UserPhoto_GetHeight();

	int CurUser_FriendPhoto_GetWidth(int FriendIndex);
	int CurUser_FriendPhoto_GetHeight(int FriendIndex);

	//app and non-app friends routines
	int CurUser_AppFriends_GetCount();
	int CurUser_AppFriends_GetCommonIndex(int AppFriendIndex);
	
	int CurUser_NonAppFriends_GetCount();
	int CurUser_NonAppFriends_GetCommonIndex(int NonAppFriendIndex);




	//notification sending routine
	bool CurUser_SendNotification(std::list<std::string>& UserIDs, const std::string& NotificationFBML);

	//feed item posting routine
	bool CurUser_PostFeedItem(FACEBOOK_FEEDITEM ItemType, const FacebookFeedItem& FeedItemInfo);

protected:

	//METHODS

    /// Not implemented to prevent copying
    Facebook( const Facebook & );     
    Facebook& operator=( const Facebook & );


	//helper methods
	void Helper_LogoutUser(FacebookUser* pUser);
	bool Helper_CreateSession();
	void Helper_ParseProfileInfo(XMLNode& UserInfoNode, FacebookProfileInfo& Result);
	void Helper_FillInfoFieldFromProfile(FACEBOOK_PROFILEINFO InfoField, const FacebookProfileInfo& ProfileInfo, std::string& Result);

	void Helper_GetPhotoSize(const std::string& PhotoURL, FacebookPhotoSize& Result);

	bool Helper_FetchPhoto(const std::string& PhotoURL, std::string& Result);

	void Helper_BuildAppAndNonAppVectors(FacebookUser* pUser);

	void Helper_SaveRequestResultToFile(std::string& RequestResult);

	//helper request methods
	void HelperRequest_MakeMD5(const std::string& SourceString, std::string& Result);
	void HelperRequest_GetParamsString(std::list<std::string>& Params, bool Separate, std::string& Result);
	void HelperRequest_GetSignature(std::list<std::string>& Params, std::string& Result);
	bool HelperRequest_CallAPIMethod(const std::string& Method, std::list<std::string>& Params, std::string& Result);

	//MEMBERS

	//callback func pointer
	FacebookCallbackFunc		m_pCallbackFunc;

	//main data

	std::string					m_AppKey;
	std::string					m_AppSecret;
	std::string					m_ApiServer;
	std::string					m_LoginURL;

	int							m_CallID;

	//error description
	std::string					m_ErrorDescription;
	bool						m_FacebookSiteChanged;
	bool						m_InvalidLoginPassword;

	//users
	std::list<FacebookUser*>	m_UsersList;
	FacebookUser*				m_pCurUser;

};//class Facebook






























#endif